package monolithicapp

import (
	"context"
	"fmt"
	"log/slog"
	"net/http"
	"os"

	"github.com/go-playground/validator/v10"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

type CustomValidator struct {
	validator *validator.Validate
}

func (cv *CustomValidator) Validate(i any) error {
	if err := cv.validator.Struct(i); err != nil {
		// Optionally, you could return the error to give each route more control over the status code
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	return nil
}

type HTTPServer struct {
	config         *HTTPConfig
	e              *echo.Echo
	api            *echo.Group
	rootMiddleware []echo.MiddlewareFunc
	rootHandler    func(e *echo.Echo)
	apiMiddleware  []echo.MiddlewareFunc
	apiHandler     func(g *echo.Group)
	staticHandle   func() echo.HandlerFunc
}

func NewHttp(config *HTTPConfig) *HTTPServer {
	return &HTTPServer{config: config, e: echo.New()}
}

func (h *HTTPServer) Start() error {

	if h.config == nil {
		slog.Error("http config is nil... ")
		return fmt.Errorf("http config is nil")
	}

	if h.config.Address == "" {
		slog.Error("http config is invalid... ")
		return fmt.Errorf("http config is invalid")
	}

	h.e.Validator = &CustomValidator{validator: validator.New()}
	h.e.Use(middleware.Recover() /*, middleware.RequestID()*/)
	// h.e.Use(middleware.BodyDumpWithConfig(h.bodyDumpConfig()))
	h.e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Skipper: func(context echo.Context) bool {
			return false
		},
		CustomTimeFormat: "2006-01-02 15:04:05",
		Format:           "Echo ${time_custom} ${status} ${method} ${id} ${uri}\n",
	}))
	h.e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins:  []string{"*"},
		AllowHeaders:  []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept},
		AllowMethods:  []string{echo.GET, echo.POST},
		ExposeHeaders: []string{echo.HeaderAuthorization},
	}))

	if h.rootMiddleware != nil {
		h.e.Use(h.rootMiddleware...)
	}

	if h.rootHandler != nil {
		h.rootHandler(h.e)
	}

	if h.staticHandle != nil {
		h.e.GET("/*", h.staticHandle())
	}

	h.api = h.e.Group("/api")

	if h.apiMiddleware != nil {
		h.api.Use(h.apiMiddleware...)
	}

	if h.apiHandler != nil {
		h.apiHandler(h.api)
	}

	go func() {
		err := h.e.Start(h.config.Address)
		if err != nil {
			slog.Error(err.Error())
			os.Exit(1)
		}
	}()
	slog.Info("http started...")
	return nil
}

func (h *HTTPServer) StaticHandle(fn func() echo.HandlerFunc) {
	h.staticHandle = fn
}

func (h *HTTPServer) ApiMiddleware(mf ...echo.MiddlewareFunc) {
	h.api.Use(mf...)
}

func (h *HTTPServer) RootMiddleware(mf ...echo.MiddlewareFunc) {
	h.e.Use(mf...)
}

func (h *HTTPServer) Stop(ctx context.Context) error {
	return h.e.Close()
}

func BodyDumpConfig(skipper func(c echo.Context) bool, handler func(c echo.Context, reqBody []byte, resBody []byte)) middleware.BodyDumpConfig {
	return middleware.BodyDumpConfig{
		Skipper: skipper,
		Handler: handler,
		//  func(c echo.Context, reqBody []byte, resBody []byte) {
		// println("API请求结果拦截：", string(reqBody), string(resBody))
		// 1、解析返回的json数据，判断接口执行成功或失败。如： {"code":"200","data":"test","msg":"请求成功"}
		// 2、保存操作日志
		// go SaveLog(c, h.cache, reqBody, resBody)
		// },
	}
}
